
<script lang="ts" setup>
// codemirror api https://codemirror.net/docs/guide/
import { EditorState, Text, Compartment } from '@codemirror/state';
import { basicSetup, EditorView } from 'codemirror';
import { keymap, lineNumbers } from '@codemirror/view';
import { defaultKeymap } from '@codemirror/commands';
import { oneDark } from '@codemirror/theme-one-dark';

import { json, jsonParseLinter } from '@codemirror/lang-json';
import { css } from '@codemirror/lang-css';
import { cpp } from '@codemirror/lang-cpp';
import { html } from '@codemirror/lang-html';
import { java } from '@codemirror/lang-java';
import { javascript as js } from '@codemirror/lang-javascript';
import { markdown as md } from '@codemirror/lang-markdown';
import { python as py } from '@codemirror/lang-python';
import { sql } from '@codemirror/lang-sql';
import { rust } from '@codemirror/lang-rust';
import { vue } from '@codemirror/lang-vue';
import { xml } from '@codemirror/lang-xml';
import { saveTextAsFile } from '/@/libs/utils/download';
const props = defineProps({
  fileText: {
    type: String,
    default: 'hello word!', //文本
  },
  fileType: {
    type: String,
    default: 'json', // 编辑模式(文件类型)
  },
});

const data = reactive({
  fontSize: '14',
  theme: 'dark', // codeMirror主题
  // readOnly: true,
  readEdit: true,
  lineNumber: true,
});

const editorContainer: Ref<InstanceType<typeof Element> | undefined> = ref();

onMounted(() => {});
onUnmounted(() => {
  view?.destroy();
});
watch(
  () => props.fileText,
  (n) => {
    init();
  },
);

let view: any;
const init = () => {
  view?.destroy();
  let startState = EditorState.create({
    doc: props.fileText,
    extensions: [
      data.lineNumber ? basicSetup : [],
      data.theme == 'default' ? [] : oneDark,
      EditorState.readOnly.of(!data.readEdit),
      textType(props.fileType),
      // 自定义主题

      // EditorView.theme(
      //   {
      //     '&': {
      //       color: 'white',
      //       backgroundColor: '#034',
      //     },
      //     '.cm-content': {
      //       caretColor: '#0e9',
      //     },
      //     '&.cm-focused .cm-cursor': {
      //       borderLeftColor: '#0e9',
      //     },
      //     '&.cm-focused .cm-selectionBackground, ::selection': {
      //       backgroundColor: '#074',
      //     },
      //     '.cm-gutters': {
      //       backgroundColor: '#045',
      //       color: '#ddd',
      //       border: 'none',
      //     },
      //   },
      //   { dark: true },
      // ),
    ],
    // extensions: [keymap.of(defaultKeymap)],
  });
  view = new EditorView({
    state: startState,
    parent: unref(editorContainer),
  });
};
const textType = (type: string) => {
  // if (supportType.includes(type)) {
  //   // eval 将字符串转化为函数
  //   return eval(type + '()');
  // } else {
  //   return keymap.of(defaultKeymap);
  // }
  return type == 'json'
    ? json()
    : type == 'css'
    ? css()
    : type == 'cpp'
    ? cpp()
    : type == 'html'
    ? html()
    : type == 'java'
    ? java()
    : type == 'js' || type == 'ts'
    ? js()
    : type == 'md'
    ? md()
    : type == 'py'
    ? py()
    : type == 'sql'
    ? sql()
    : type == 'rust'
    ? rust()
    : type == 'vue'
    ? vue()
    : type == 'xml'
    ? xml()
    : keymap.of(defaultKeymap);
};
//节流
let timer_throttle: any;
const throttle = (fn: Function, wait?: number) => {
  wait = wait || 100;
  if (!timer_throttle) {
    timer_throttle = setTimeout(() => {
      fn.apply(this);
      timer_throttle = null;
    }, wait);
  }
};

const handFontSize = (value: string) => {
  let cmContent = document.querySelector('.cm-content');
  if (cmContent) {
    cmContent.style.fontSize = value + 'px';
  }
};
const handTheme = (value: string) => init();

const handLineNumber = (value: boolean) => init();

const handReadOnly = (value: boolean) => init();
const saveFile = () => {
  console.log(view?.state.doc.toString());
  saveTextAsFile(view?.state.doc.toString(), 'newFile.' + props.fileType);
};
</script>
<template>
  <div class="flex-end mt-3 mb-2">
    <a-space class="flex-wrap">
      <a-button type="primary" v-if="data.readEdit" @click="saveFile">保存</a-button>
      <a-select v-model:value="data.fontSize" class="w-px-100" @change="handFontSize">
        <a-select-option value="12">12px</a-select-option>
        <a-select-option value="14">14px</a-select-option>
        <a-select-option value="16">16px</a-select-option>
        <a-select-option value="18">18px</a-select-option>
      </a-select>
      <a-select v-model:value="data.theme" class="w-px-100" @change="handTheme">
        <a-select-option value="default">默认</a-select-option>
        <a-select-option value="dark">dark</a-select-option>
      </a-select>
      <a-switch
        checked-children="显示行号"
        un-checked-children="不显示"
        v-model:checked="data.lineNumber"
        @change="handLineNumber"
      />
      <a-switch
        checked-children="可编辑"
        un-checked-children="不可编辑"
        v-model:checked="data.readEdit"
        @change="handReadOnly"
      />
    </a-space>
  </div>
  <!-- 这里一定要指定高度并设置 overflow：auto; 否则加载文件会卡死，加overflow这个插件已经给你做好了懒加载 -->
  <div ref="editorContainer" id="editorContainer" class="overflow-auto h-px-600"></div>

  <!-- <CodemirrorCodemirror :value="fileText" :fileType :lineNumber :readOnly :theme="data.theme" /> -->
</template>

<style lang="less" scoped>
#editorContainer {
  height: calc(90vh - 92px);
}
</style>
